/**
 * 
 */
package edu.umd.clip.lm.ngram;

import java.io.Serializable;

import edu.umd.clip.lm.factors.*;
import edu.umd.clip.lm.model.Experiment;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class CtxVar implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private final boolean hidden; // -1 denotes hidden factors
	private final byte offset; // 0 denotes future
	
	public CtxVar(byte offset, boolean hidden) {
		this.hidden = hidden;
		this.offset = offset;
	}
	
	public byte getOffset() {
		return offset;
	}
	
	public boolean isHidden() {
		return hidden;
	}
	
	public int getValue(long ctx[]) {
		long tuple = ctx[ctx.length+offset];
		return getValue(tuple);
	}
	
	public void setValue(long ctx[], int value) {
		ctx[ctx.length+offset] = setValue(ctx[ctx.length+offset], value);
	}
	
	public int getValue(long tuple) {
		FactorTupleDescription desc = Experiment.getInstance().getTupleDescription();
		
		if (isHidden()) {
			return desc.packHiddenFactorsToInt(tuple & desc.getHiddenFactorsMask());
		} 
		return desc.packOvertFactorsToInt(tuple & desc.getOvertFactorsMask());		
	}
	
	public int getValue(long ctx[], long futureTuple) {
		long tuple = futureTuple;
		if (offset < 0) {
			tuple = ctx[ctx.length+offset];
		}
		return getValue(tuple);
	}
	
	public long setValue(long tuple, int value) {
		FactorTupleDescription desc = Experiment.getInstance().getTupleDescription();
		
		if (isHidden()) {
			return (tuple & desc.getOvertFactorsMask()) | desc.unpackHiddenFactorsFromInt(value);
		} 
		return (tuple & desc.getHiddenFactorsMask()) | desc.unpackOvertFactorsFromInt(value);		
		
	}

	@Override
	public String toString() {
		return (hidden ? "T@" : "W@") +  offset;
	}
}
